n_layers = 6
src_vocab_size = 6
class Encoder(nn.Module):
    def __init__(self):
        super(Encoder, self).__init__()
        # 对encoder的输入的每个单词进行词向量计算词向量 
        # 如：src_vocab_size个词,每个词d_model的维度 
        self.src_emb = nn.Embedding(src_vocab_size, d_model)
       
        # 计算位置向量
        self.pos_emb = PositionalEncoding(d_model)
        # 将6个EncoderLayer组成一个module     
        # 用nn.ModuleList循环组成6层EncoderLayer,通常这么使用
        self.layers = nn.ModuleList([EncoderLayer()  for _ in range(n_layers)])
    def forward(self, enc_inputs):
        '''
        enc_inputs: [batch_size, src_len]
        '''
         # 对每个单词进行词向量计算
        enc_outputs = self.src_emb(enc_inputs) #(2,5,512)       
        # enc_outputs [batch_size, src_len, d_model]

        # enc_outputs = self.pos_emb(enc_outputs.transpose(0,1)).transpose(0, 1)
        enc_outputs = self.pos_emb(enc_outputs)
        # x.transpose(0, 1) <==> x.transpose(1, 0)
        # transpose：指定哪两个维度交换
        # permute：直接按照指定顺序交换
        # 添加位置编码
        #  enc_outputs [batch_size, src_len, d_model]

        # 计算得到encoder-attention的pad martix
        enc_self_attn_mask = get_attn_pad_mask(enc_inputs,enc_inputs)
        # 用循环组成6层,通常都这么实现
        for layer in self.layers:            
            enc_outputs = layer(enc_outputs, enc_self_attn_mask)
            # enc_outputs: [batch_size, src_len, d_model]
        return enc_outputs
